#pragma once
#include <type_traits>
#include <boost/algorithm/string.hpp>
#include <boost/lexical_cast.hpp>

class AbsoluteOrRelativeValue
{
public:
    constexpr AbsoluteOrRelativeValue() = default;

    template <typename T,typename = typename std::enable_if_t<std::is_arithmetic<T>::value,T>>
    AbsoluteOrRelativeValue(T constant):
        constant(true),
        value(static_cast<float>(constant))
        {
        }

    AbsoluteOrRelativeValue(const std::string& expression)
    {
        if(boost::algorithm::ends_with(expression,"%"))
        {
            constant = false;
            ratio = boost::lexical_cast<float>(expression.substr(0, expression.length()-1))*0.01f;
        }
        else
        {
            constant = true;
            ratio = boost::lexical_cast<float>(expression);
        }
    }

    float getValue() const
    {
        return value;
    }

    float getRatio() const
    {
        return ratio;
    }

    bool isConstant() const
    {
        return constant;
    }

    void updateParentSize(float newParentSize)
    {
        if(!constant)
        {
            parentValue = newParentSize;
            value = ratio*newParentSize;
        }
    }

    std::string toString()const
    {
        if(constant)
            return boost::lexical_cast<std::string>(value);
        else
            return boost::lexical_cast<std::string>(ratio) + '%';
    }
protected:
    bool  constant = true;
    float value = 0;
    float ratio = 0;
    float parentValue = 0;
};

struct RelativeValue : AbsoluteOrRelativeValue
{
    explicit constexpr RelativeValue(float newRatio)
    {
        constant = false;
        ratio = newRatio;
    }
};
